package com.laiyw.monitor.core;

import com.alibaba.fastjson.JSONObject;
import com.laiyw.monitor.utils.ByteUtils;
import com.laiyw.monitor.utils.DateUtils;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.RuntimeMXBean;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 * @Auther: Laiyw
 * @Date: 2018/10/4 17:25
 */
public abstract class ServerMonitorInfo {

    /**
     * cpu使用率
     *
     * @return
     */
    public abstract Double cpuUsedPercent();

    /**
     * 服务器内存使用率
     *
     * @return
     */
    public abstract Double sysMemoryUsedPercent();

    /**
     * jvm内存使用率
     *
     * @return
     */
    public Double jvmMemoryUsedPercent() {
        Runtime runtime = Runtime.getRuntime();
        long used = runtime.totalMemory() - runtime.freeMemory();
        return used * 1.0 / runtime.totalMemory() * 100;
    }

    /**
     * 服务器信息
     *
     * @return
     */
    public abstract JSONObject getServerInfo();

    /**
     * 服务器磁盘信息
     *
     * @return
     */
    public abstract List<JSONObject> getServerDisk();

    /**
     * 服务器处理器信息
     *
     * @return
     */
    public abstract List<JSONObject> getServerCpuListInfo();

    /**
     * 服务器内存信息
     *
     * @return
     */
    public abstract JSONObject getServerMemory();

    /**
     * Java虚拟机信息
     *
     * @return
     */
    public JSONObject getJvmInfo() {
        JSONObject json = new JSONObject();
        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
        json.put("name", bean.getVmName());//虚拟机实现名称
        json.put("runVersion", bean.getSystemProperties().get("java.version"));//行环境版本
        json.put("vmVersion", bean.getVmVersion());//虚拟机实现版本
        json.put("vmVendor", bean.getVmVendor());//虚拟机实现供应商
        json.put("installDir", bean.getSystemProperties().get("java.home"));//安装路径
        json.put("tmpDir", bean.getSystemProperties().get("java.io.tmpdir"));//默认的临时文件路径
        json.put("extDirs", bean.getSystemProperties().get("java.ext.dirs"));//扩展目录的路径
        json.put("classPath", bean.getSystemProperties().get("java.class.path"));//Java类路径
        json.put("startTime", DateUtils.formatDate(bean.getStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS));//启动时间
        json.put("runtime", DateUtils.formatDateAgo(bean.getUptime()));//运行时长
        json.put("inputArguments", bean.getInputArguments());//启动参数
        return json;
    }

    /**
     * Java虚拟机总内存信息
     *
     * @return
     */
    public JSONObject getJvmMemory() {
        JSONObject json = new JSONObject();
        Runtime runtime = Runtime.getRuntime();
        json.put("jvmMax", ByteUtils.formatByteSize(runtime.maxMemory()));//jvm能使用的最大内存
        json.put("jvmTotal", ByteUtils.formatByteSize(runtime.totalMemory()));//jvm总内存
        json.put("jvmFree", ByteUtils.formatByteSize(runtime.freeMemory()));//空闲内存，相对于totalMemory
        long used = runtime.totalMemory() - runtime.freeMemory();
        json.put("jvmUsed", ByteUtils.formatByteSize(used));//已用
        json.put("usedPercent", (int) (used * 1.0 / runtime.totalMemory() * 100) + "%");//使用率
        return json;
    }

    /**
     * Java虚拟机 堆/非堆内存信息
     *
     * @return
     */
    public JSONObject getHeapMemory() {
        JSONObject json = new JSONObject();
        MemoryMXBean mxb = ManagementFactory.getMemoryMXBean();
        json.put("heapMax", ByteUtils.formatByteSize(mxb.getHeapMemoryUsage().getMax()));//最大
        json.put("heapInit", ByteUtils.formatByteSize(mxb.getHeapMemoryUsage().getInit()));//初始化
        json.put("heapUsed", ByteUtils.formatByteSize(mxb.getHeapMemoryUsage().getUsed()));//已用
        json.put("heapCommitted", ByteUtils.formatByteSize(mxb.getHeapMemoryUsage().getCommitted()));
        json.put("heapAvailable", ByteUtils.formatByteSize(mxb.getHeapMemoryUsage().getMax() - mxb.getHeapMemoryUsage().getUsed()));//可用

        long nonHeapMax = mxb.getNonHeapMemoryUsage().getMax();
        json.put("nonHeapMax", ByteUtils.formatByteSize(nonHeapMax));
        json.put("nonHeapInit", ByteUtils.formatByteSize(mxb.getNonHeapMemoryUsage().getInit()));
        json.put("nonHeapUsed", ByteUtils.formatByteSize(mxb.getNonHeapMemoryUsage().getUsed()));
        json.put("nonHeapCommitted", ByteUtils.formatByteSize(mxb.getNonHeapMemoryUsage().getCommitted()));
        json.put("nonHeapAvailable", nonHeapMax < 0 ? nonHeapMax : ByteUtils.formatByteSize(nonHeapMax - mxb.getNonHeapMemoryUsage().getUsed()));
        return json;
    }

    /**
     * Java虚拟机 堆/非堆内存的详细信息
     *
     * @return
     */
    public List<JSONObject> getHeapMemoryPool() {
        List<JSONObject> jsonObjectList = new ArrayList<JSONObject>();
        List<MemoryPoolMXBean> mxb = ManagementFactory.getMemoryPoolMXBeans();
        JSONObject json = null;
        long max, used;
        String usedPercent;
        for (MemoryPoolMXBean memoryPoolMXBean : mxb) {
            json = new JSONObject();
            usedPercent = "0%";
            json.put("type", memoryPoolMXBean.getType());//内存类型
            json.put("name", memoryPoolMXBean.getName());//内存名称
            json.put("managerNames", String.join(",", memoryPoolMXBean.getMemoryManagerNames()));
            max = memoryPoolMXBean.getUsage().getMax();
            json.put("usageMax", ByteUtils.formatByteSize(max));
            json.put("usageInit", ByteUtils.formatByteSize(memoryPoolMXBean.getUsage().getInit()));
            json.put("usageCommitted", ByteUtils.formatByteSize(memoryPoolMXBean.getUsage().getCommitted()));
            used = memoryPoolMXBean.getUsage().getUsed();
            json.put("usageUsed", ByteUtils.formatByteSize(used));
            if (max > 0) {
                usedPercent = new DecimalFormat("#0.00%").format(used * 1.0 / max);
            }
            json.put("usageUsedPercent", usedPercent);//内存使用率
            jsonObjectList.add(json);
        }
        return jsonObjectList;
    }
}
